package com.apartment.own.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import com.apartment.common.exception.CustomException;
import com.apartment.common.utils.BigDecimalUtils;
import com.apartment.common.utils.DateUtils;
import com.apartment.common.utils.MyDateUtils;
import com.apartment.common.utils.date.MyDetail;
import com.apartment.common.utils.date.SplitDateUtil;
import com.apartment.own.domain.*;
import com.apartment.own.domain.enums.*;
import com.apartment.own.mapper.OwnAccountInstallmentMapper;
import com.apartment.own.request.bills.BillPreviewDTO;
import com.apartment.own.request.bills.CashPledge;
import com.apartment.own.request.bills.Cost;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.apartment.own.mapper.OwnAccountDetailsMapper;
import com.apartment.own.service.IOwnAccountDetailsService;


/**
 * 账单详情Service业务层处理
 *
 * @author @Dog_E
 * @date 2020-08-28
 */
@Service
public class OwnAccountDetailsServiceImpl extends ServiceImpl<OwnAccountDetailsMapper, OwnAccountDetails> implements IOwnAccountDetailsService {


    @Autowired
    private OwnAccountDetailsMapper ownAccountDetailsMapper;
    @Autowired
    private OwnAccountInstallmentMapper ownAccountInstallmentMapper;
    @Autowired
    private OwnAccountInstallmentServiceImpl ownAccountInstallmentService;


    /**
     * 查询账单详情
     *
     * @param id 账单详情ID
     * @return 账单详情
     */
    @Override
    public OwnAccountDetails selectOwnAccountDetailsById(Long id) {
        return ownAccountDetailsMapper.selectOwnAccountDetailsById(id);
    }

    /**
     * 查询账单详情列表
     *
     * @param ownAccountDetails 账单详情
     * @return 账单详情
     */
    @Override
    public List<OwnAccountDetails> selectOwnAccountDetailsList(OwnAccountDetails ownAccountDetails) {
        return ownAccountDetailsMapper.selectOwnAccountDetailsList(ownAccountDetails);
    }

    /**
     * 新增账单详情
     *
     * @param ownAccountDetails 账单详情
     * @return 结果
     */
    @Override
    public int insertOwnAccountDetails(OwnAccountDetails ownAccountDetails) {
        ownAccountDetails.setCreateTime(DateUtils.getNowDate());
        return ownAccountDetailsMapper.insertOwnAccountDetails(ownAccountDetails);
    }

    /**
     * 修改账单详情
     *
     * @param ownAccountDetails 账单详情
     * @return 结果
     */
    @Override
    public int updateOwnAccountDetails(OwnAccountDetails ownAccountDetails) {
        ownAccountDetails.setUpdateTime(DateUtils.getNowDate());
        return ownAccountDetailsMapper.updateOwnAccountDetails(ownAccountDetails);
    }

    /**
     * 批量删除账单详情
     *
     * @param ids 需要删除的账单详情ID
     * @return 结果
     */
    @Override
    public int deleteOwnAccountDetailsByIds(Long[] ids) {
        return ownAccountDetailsMapper.deleteOwnAccountDetailsByIds(ids);
    }

    /**
     * 删除账单详情信息
     *
     * @param id 账单详情ID
     * @return 结果
     */
    @Override
    public int deleteOwnAccountDetailsById(Long id) {
        return ownAccountDetailsMapper.deleteOwnAccountDetailsById(id);
    }

    //TODO:Des-> 账单开始时间和结束时间有问题,当账单提前的时候 ,这个开始时间和结束时间也要变化  问题类型->BUG   创建人-> RazaJin 创建时间->  2020/9/16 0016 下午 5:45  预计解决时间->
    @Override
    public void createPaymentList(OwnResHouseContract request) {

        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            //账单开始时间和逻辑字段
            String leaseStartTime = simpleDateFormat.format(request.getLeaseStartTime());
            //账单结束时间
            String leaseEndTime = simpleDateFormat.format(request.getLeaseEndTime());
            //一次付多少钱
            Double accountPayable = request.getAccountPayable().doubleValue();
            //多久一次付款
            //TODO:Des-> 这个不能直接取值 必须区枚举里面的值并判断  问题类型-> ERROR  创建人-> RazaJin 创建时间->  2020/9/16 0016 下午 6:17  预计解决时间->
            Integer leasePaymentType = request.getLeasePaymentType().intValue();

            List<MyDetail> keyValueForDate;
            //创建账单详情对象
            PaymentTimeTypeEnum leasePaymentTypeEnum = PaymentTimeTypeEnum.getEnum(request.getPayTime().intValue());
            Integer pushDay = request.getPayTimeValue();
            switch (leasePaymentTypeEnum) {
                case BeforeTheBillStarts:
                    keyValueForDate = SplitDateUtil.getSplitDate(leaseStartTime, leaseEndTime, leasePaymentType, accountPayable, pushDay, 0.0);
                    break;
                case FixTheBillBeforeStart:
                case FixTheBillWhenItStarts:
                    keyValueForDate = SplitDateUtil.getSplitDate(leaseStartTime, leaseEndTime, leasePaymentType, accountPayable, pushDay, 0.0);
                    break;//这个没法做用默认的
                //keyValueForDate = SplitDateUtil.getKeyValueForDate(leaseStartTime, leaseEndTime, leasePaymentType, accountPayable,-30 + pushDay);
                default:
                    keyValueForDate = SplitDateUtil.getSplitDate(leaseStartTime, leaseEndTime, leasePaymentType, accountPayable, pushDay, 0.0);
            }

            //关于押金部分

            //关于加收费用部分


            //创建账单对象 这里只创建一个简答的账单对象,获取这个账单的主键
            OwnAccountDetails ownAccountDetail = new OwnAccountDetails();
            ownAccountDetail.setPaymentTypeName(BillAccountTypeEnum.RENT.getId());
            //TODO:Des-> 应收款为0  问题类型->   创建人-> RazaJin 创建时间->  2020/9/16 0016 下午 5:46  预计解决时间->  
            ownAccountDetail.setReceivables(new BigDecimal("0.00"));
            ownAccountDetail.setPaymentCycleBegin(simpleDateFormat.parse(leaseStartTime));
            ownAccountDetail.setPaymentCycleEnd(simpleDateFormat.parse(leaseEndTime));
            boolean save = save(ownAccountDetail);


            List<OwnAccountInstallment> ownAccountInstallments = new ArrayList<>();
            //通过工具类生成账单付款时间

            for (int i = 0; i < keyValueForDate.size(); i++) {
                MyDetail myDetail = keyValueForDate.get(i);
                OwnAccountInstallment ownAccountInstallment = new OwnAccountInstallment(ownAccountDetail.getId(), request.getId(), i, BillAccountTypeEnum.RENT, myDetail.getStartDate(), myDetail.getEndDate(), myDetail.getRent());
                ownAccountInstallments.add(ownAccountInstallment);
            }

            List<OwnAccountInstallment> cashPlege = createCashPlege(request.getId(), leaseStartTime, leaseEndTime, request.getOwnOrdCashPledgeList(), ownAccountInstallments, ownAccountDetail.getId());
            List<OwnAccountInstallment> extraCharge = creatExtraCharge(request.getId(), leaseStartTime, leaseEndTime, request.getOwnOrdExtraChargeList(), ownAccountInstallments, ownAccountDetail.getId());
            ownAccountInstallments.addAll(cashPlege);
            ownAccountInstallments.addAll(extraCharge);

            BigDecimal decimal = new BigDecimal("0.00");
            keyValueForDate.forEach(ele -> decimal.add(ele.getRent()));
            ownAccountDetail.setReceivables(decimal);
            ownAccountDetail.setLeftPayment(decimal);
            update(ownAccountDetail, new UpdateWrapper<OwnAccountDetails>().eq("id", ownAccountDetail.getId()));

            boolean b = ownAccountInstallmentService.saveBatch(ownAccountInstallments);

            //DB
            //赋值


            //返回
        } catch (ParseException e) {
            e.printStackTrace();
            //返回
        }
    }

    /**
     * @param billPreviewDTO:账单预览参数
     * @Description: 账单预览
     * @return: com.apartment.common.core.domain.AjaxResult
     * @Author: @Dog_E
     * @Date: 2020/9/16 0016 09:53
     **/

    @Override
    public List<OwnAccountInstallment> billPreview(BillPreviewDTO billPreviewDTO) {
        List<OwnAccountInstallment> ownAccountInstallments = new ArrayList<>();
        //1.先算押金
        //1.1拿出全部附加押金
        List<CashPledge> cashPledges = billPreviewDTO.getCashPledges();
        //初始化总押金
        BigDecimal decimalTotal = BigDecimal.ZERO;
//        BigDecimal decimalTotal = null;

        //附加押金不为空的时候
        //创建押金明细

        if (Objects.nonNull(cashPledges)) {
            for (CashPledge deposit : cashPledges) {
                //押金不能为负数
                if (BigDecimalUtils.isNegative(deposit.getDeposit())) {
                    throw new CustomException("押金不能为负数");
                }
                //判断押金是否为0
                if (BigDecimalUtils.isZero(deposit.getDeposit())) {
                    throw new CustomException("押金不能为0");
                }
                //1.2附加押金相加
                decimalTotal = decimalTotal.add(deposit.getDeposit());
            }

            //1.3附加押金+常规押金
            if (!BigDecimalUtils.isZero(billPreviewDTO.getDeposit())) {
                decimalTotal = decimalTotal.add(billPreviewDTO.getDeposit());
            }

            //押金添加到集合
            OwnAccountInstallment installment = new OwnAccountInstallment(null, null, 1, BillAccountTypeEnum.CASH_PLEDGE, MyDateUtils.dateStr2(billPreviewDTO.getRent()), MyDateUtils.dateStr2(billPreviewDTO.getSurrender()), decimalTotal);
            installment.setAccountTypeName("押金");

            ownAccountInstallments.add(installment);
        }
        //附加押金为空 只添加常规押金
        else {
            //判断常规押金是否为0
            if (BigDecimalUtils.isZero(billPreviewDTO.getDeposit())) {
            }
            //押金不为0
            else {
                //押金添加到集合
                OwnAccountInstallment installment = new OwnAccountInstallment(null, null, 1, BillAccountTypeEnum.CASH_PLEDGE, MyDateUtils.dateStr2(billPreviewDTO.getRent()), MyDateUtils.dateStr2(billPreviewDTO.getSurrender()), billPreviewDTO.getDeposit());
                installment.setAccountTypeName("押金");

                ownAccountInstallments.add(installment);
            }
        }


        //2.计算租金以及附加费用
        //创建账单详情对象
        PaymentTimeTypeEnum leasePaymentTypeEnum = PaymentTimeTypeEnum.getEnum(billPreviewDTO.getPayTime().intValue());
        Integer pushDay = billPreviewDTO.getPayTimeValue();
        List<MyDetail> keyValueForDate;
        switch (leasePaymentTypeEnum) {
            case BeforeTheBillStarts:
                keyValueForDate = SplitDateUtil.getSplitDate(MyDateUtils.dateStr2(billPreviewDTO.getRent())
                        , MyDateUtils.dateStr2(billPreviewDTO.getSurrender())
                        , billPreviewDTO.getPayAFew(), billPreviewDTO.getMonthlyRent().doubleValue()
                        , pushDay, 0.0);
                break;
            case FixTheBillBeforeStart:
            case FixTheBillWhenItStarts:
                keyValueForDate = SplitDateUtil.pushFixedDay(MyDateUtils.dateStr2(billPreviewDTO.getRent())
                        , MyDateUtils.dateStr2(billPreviewDTO.getSurrender())
                        , billPreviewDTO.getPayAFew(), billPreviewDTO.getMonthlyRent().doubleValue()
                        , pushDay, 0.0);
                break;//这个没法做用默认的.
            //keyValueForDate = SplitDateUtil.getKeyValueForDate(leaseStartTime, leaseEndTime, leasePaymentType, accountPayable,-30 + pushDay);
            default:
                keyValueForDate = SplitDateUtil.getSplitDate(
                        MyDateUtils.dateStr2(billPreviewDTO.getRent())
                        , MyDateUtils.dateStr2(billPreviewDTO.getSurrender())
                        , billPreviewDTO.getPayAFew()
                        , billPreviewDTO.getMonthlyRent().doubleValue()
                        , 0, 0.0);
        }


        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        //创建账单对象 这里只创建一个简答的账单对象,获取这个账单的主键
        OwnAccountDetails ownAccountDetail = new OwnAccountDetails();
        ownAccountDetail.setPaymentTypeName(BillAccountTypeEnum.RENT.getId());

        ownAccountDetail.setReceivables(new BigDecimal("0.00"));
        try {
            ownAccountDetail.setPaymentCycleBegin(simpleDateFormat.parse(simpleDateFormat.format(billPreviewDTO.getRent())));
            ownAccountDetail.setPaymentCycleEnd(simpleDateFormat.parse(simpleDateFormat.format(billPreviewDTO.getSurrender())));
        } catch (ParseException e) {
            e.printStackTrace();
        }


        //通过工具类生成账单付款时间

        for (int i = 0; i < keyValueForDate.size(); i++) {
            MyDetail detail = keyValueForDate.get(i);
            OwnAccountInstallment ownAccountInstallment = new OwnAccountInstallment(
                    ownAccountDetail.getId()
                    , null
                    , i, BillAccountTypeEnum.RENT
                    , detail.getStartDate()
                    , detail.getEndDate()
                    , detail.getRent());
            ownAccountInstallments.add(ownAccountInstallment);
        }
        List<Cost> costs = billPreviewDTO.getCosts();
        List<OwnOrdExtraCharge> extraChargeList = new ArrayList<>();

        costs.forEach(ele -> {
            OwnOrdExtraCharge charge = new OwnOrdExtraCharge();
            charge.setExtraCostType(Long.valueOf(ele.getTypesOfFee()));
            charge.setExtraCostPayType(Long.valueOf(ele.getPayAFew()));
            charge.setCost(ele.getDeposit());
            extraChargeList.add(charge);
        });
        //额外费用
        List<OwnAccountInstallment> installments = creatExtraCharge(null
                , simpleDateFormat.format(billPreviewDTO.getRent())
                , simpleDateFormat.format(billPreviewDTO.getSurrender())
                , extraChargeList
                , ownAccountInstallments, null
        );
        ownAccountInstallments.addAll(installments);
        return ownAccountInstallments;
    }

    /**
     * des.合并账单
     * contract 合同
     * installments 生成的基础账单列表
     * list
     * 第一层循环  循环加收费用列表,根据是一次付款还是随租金付款生成账单
     * 如果是随租金付款  循环  租金付款列表  生成随租金付款的加收费用账单
     *
     * @author : RazaJin
     * @date :` 上午 11:22
     */
    public List<OwnAccountInstallment> creatExtraCharge(String contract, String beginTiem, String endTime, List<OwnOrdExtraCharge> list, List<OwnAccountInstallment> installments, String ownAccountDetailId) {
        ArrayList<OwnAccountInstallment> ownAccountInstallments = new ArrayList<>();
        list.forEach(ele -> {
            ExtraEnum extraEnum = ExtraEnum.getEnum(ele.getExtraCostPayType().intValue());
            switch (extraEnum) {
                case TYPE1:
                    //一次付清
                    OwnAccountInstallment ownAccountInstallment = new OwnAccountInstallment(ownAccountDetailId, contract, 1, BillAccountTypeEnum.EXTRA_CHARGE, beginTiem, endTime, ele.getCost());
                    ownAccountInstallments.add(ownAccountInstallment);
                    break;
                case TYPES:
                    //随租金付清
                    for (int i = 0; i < installments.size(); i++) {
                        //这个是基础账单的列表
                        OwnAccountInstallment installment = installments.get(i);
                        //这个是加收费用账单列表
                        OwnAccountInstallment ownAccountInstallment2 = new OwnAccountInstallment(
                                ownAccountDetailId
                                , contract
                                , (1), BillAccountTypeEnum.EXTRA_CHARGE
                                ,MyDateUtils.dateStr2( installment.getBillBeginTime())
                                ,MyDateUtils.dateStr2( installment.getBillEndTime())
                                , ele.getCost());
                        //TODO:Des-> 费用名字不完整,查询字典表  问题类型-> 功能不完善  创建人-> RazaJin 创建时间->  2020/9/16 0016 下午 2:49  预计解决时间->
                        ownAccountInstallment2.setAccountTypeName("加收费用第" + i + "期");
                        ownAccountInstallments.add(ownAccountInstallment2);
                    }
                    break;
                default:
            }

        });
        return ownAccountInstallments;
    }

    public List<OwnAccountInstallment> createCashPlege(String contract, String beginTiem, String endTime, List<OwnOrdCashPledge> list, List<OwnAccountInstallment> installments, String ownAccountDetailId) {
        //处理押金
        ArrayList<OwnAccountInstallment> ownAccountInstallments = new ArrayList<>();
        list.forEach(ele -> {
            OwnAccountInstallment ownAccountInstallment = new OwnAccountInstallment(ownAccountDetailId, contract, 1, BillAccountTypeEnum.CASH_PLEDGE, beginTiem, endTime, ele.getCost());
            //TODO:Des-> 押金名字不完整需要增加什么押金 查询字典表 问题类型:功能不完善,不影响使用  创建人-> RazaJin 创建时间->  2020/9/16 0016 下午 2:45  预计解决时间-> 再说吧
            ownAccountInstallment.setAccountTypeName("押金");
            ownAccountInstallments.add(ownAccountInstallment);
        });
        return ownAccountInstallments;
    }


    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0");
        List<Testss> testsses = new ArrayList<>();
        testsses.add(new Testss(new BigDecimal("1")));
        testsses.add(new Testss(new BigDecimal("1")));
        for (Testss testss : testsses) {
            a = a.add(testss.tb);

        }
        System.out.println("a = " + a);

    }

}

class Testss {
    public BigDecimal tb;

    public Testss(BigDecimal tb) {
        this.tb = tb;
    }

    public Testss() {
    }


}





































